﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.OracleClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Util
{
    public class SQLHelpr
    {        
        public static string GetConn()
        {
            //从配置文件中获取连接字符串
            string getconn = ConfigurationManager.ConnectionStrings["connstr"].ConnectionString;
            return getconn;
        }
        //SQLHelper.ExecuteNonQuery()调用方法如下:
        //SQLHelper.ExecuteNonQuery("insert into [promary] (proID,proName)values(:id,:name)",new OracleParameter("id",36),new OracleParameter("name","日本省"));
        //params OracleParameter[] parameter 是一个可变参数的OracleParameter类型数组。
        public static int ExecuteNonQuery(string sql, params OracleParameter[] parameter)
        {
            SQLHelpr.GetConn();
            using (OracleConnection conn = new OracleConnection(SQLHelpr.GetConn())) 
            {
                conn.Open();
                using (OracleCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    foreach (OracleParameter s in parameter)
                    {
                        cmd.Parameters.Add(s);
                    }
                    //cmd.ExecuteNonQuery()可以返回一个执行SQL语句所影响到的行数（一般我们不需要这个返回值，所以不写返回值）
                    return cmd.ExecuteNonQuery();

                }
            }
        }
        //SQLHelper.ExecuteScalar()调用方法如下：
        //SQLHelper.ExecuteScalar("select count(*)from xs");  或者
        //SQLHelper.ExecuteSalar("select  count(*) from xs where 专业名=@zym",new OracleParameter("zym","计算机"));

        //ExcuteScalar()的返回值是object类型的（如果想返回int类型的数据，可先将cmd.ExecuteSalar()转化成int类型再进行返回）
        public static object ExecuteScalar(string sql, params OracleParameter[] parameter)
        {
            SQLHelpr.GetConn();
            using (OracleConnection conn = new OracleConnection(SQLHelpr.GetConn()))
            {
                conn.Open();
                using (OracleCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    foreach (OracleParameter s in parameter)
                    {
                        cmd.Parameters.Add(s);
                    }
                    return cmd.ExecuteScalar();

                }
            }
        }
        //SQLHelper.DataSet() 调用方法如下：
        /*
        DataTable dt = SQLHelper.DataSet("select * from xs where 专业名=@xh", new OracleParameter("xh", "计算机"));
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            DataRow drow = dt.Rows[i];//先取到dt表的第i行
            //string name =Convert.ToString( drow[0]); //然后再取该行的第一列(索引从0开始)
            string name = Convert.ToString(drow["姓名"]);//或者写成这样也可以。然后再取该行的"姓名"列
            MessageBox.Show(name); 
                
        }
        */
        //DataSet是将查询结果填充到本地内存中，这样即使与连接断开，服务器的连接断开，都不会影响数据的读取。但是它也有一个坏处，就是只有小数据量才能往里面存放，数据量大了就给你的本地内存冲爆了。电脑会卡死去。大数据量的话还得用SqlDataReader
        public static DataTable DataSet(string sql, params OracleParameter[] parameter)
        {
            SQLHelpr.GetConn();
            using (OracleConnection conn = new OracleConnection(SQLHelpr.GetConn()))
            {
                conn.Open();
                using (OracleCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    foreach (OracleParameter s in parameter)
                    {
                        cmd.Parameters.Add(s);
                    }
                    DataSet ds = new DataSet();//或者直接用DataTable dt = new DataTable()                                       
                    using (OracleDataAdapter dr = new OracleDataAdapter(cmd))
                    {
                        //dr.Fill(dt);//如果上面是直接用DataTable对象的话这里写这条语句就好了。把数据直接填充到DataTable表里。而是不填充到DataSet表集合里
                        dr.Fill(ds);
                        DataTable dt = ds.Tables[0]; //一个ds里面可以有很多个DataTabale表，这里我们取它的第一个表。（索引从0开始）         
                        return dt; //返回一个DataTable类型名字为dt的表
                    }
                }
            }
        }
        //*******************************************************************错误的用法ExecuteReader用法   
        /*//调用方法（）
        SqlDataReader dr=SQLHelper.ExecuteReader("select * from xs");
           while (dr.Read())
           {
               string name = dr.GetString(dr.GetOrdinal("姓名"));
               MessageBox.Show(name);
           }
         */
        //其实这样是不行的。因为SqlDataReader对象在读取数据的时候需要一直连接数据库。也就是说conn连接要一直打开。当你调用SQLHelper.ExecuteReader()方法后，在using语句在结束时会先调用close方法关闭conn连接。然后自动调用欲被清除对象的Dispose()方法，来销毁这个连接。所以这个时候就会报错【阅读器关闭时尝试调用 Read 无效。】所以这个时候我们需要DataSet
        //SqlDataReader对于小数据带来的是在麻烦，优点可以忽略不计，因为它是一条一条的读取服务器上的数据，数据少，或者数据多，对于内存来说基本上没有区别。所以，一般只有大数据的时候才会考虑用SqlDataReader
        public static OracleDataReader ExecuteReader(string sql, params OracleParameter[] parameter)
        {
            SQLHelpr.GetConn();
            using (OracleConnection conn = new OracleConnection(SQLHelpr.GetConn()))
            {
                conn.Open();
                using (OracleCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    foreach (OracleParameter s in parameter)
                    {
                        cmd.Parameters.Add(s);
                    }
                    //cmd.ExecuteReader()的返回值就是一个SqlDataReader类型
                    return cmd.ExecuteReader();
                }
            }
        }         
    }
}
